<template>
  <vxe-grid
  ref='xGrid' 
  v-bind="gridOptions"
  @checkbox-change="checkboxChange"
  @checkbox-all="checkboxAll"
  @checkbox-range-change="checkboxRangeChange">
    <template #form>
      <slot name="form"></slot>
    </template>

    <template #tools_>
      <!-- <span style="margin-right: .7rem;">
        <vxe-button circle icon="vxe-icon-setting"></vxe-button>
      </span> -->
    </template>

    <!-- left -->
    <template #toolbar_buttons>
      <slot name="topLeft1"></slot>
      <Divider type="vertical"/>
      <span v-for="(v, i) in buttons.topLeft" :key="`i-${i}`" style="margin-right: 1rem;">
        <Popconfirm
v-if="v.tip"
          placement="top"
          :title="v.tipContent"
          @confirm="handleCall(v)">
          <vxe-button v-if="v.selectedCount!==1" :icon="v.icon">{{v.name}}</vxe-button>
          <vxe-button v-else :icon="v.icon">{{v.name}} {{checkboxCount}}</vxe-button>
        </Popconfirm>
        <vxe-button v-else-if="v.selectedCount!==1" :icon="v.icon" @click="handleCall(v)">{{v.name}}</vxe-button>
        <vxe-button v-else :icon="v.icon" @click="handleCall(v)">{{v.name}} {{checkboxCount}}</vxe-button>
      </span>
      <slot name="topLeft2"></slot>
    </template>

    <!-- operate -->
    <template #operate="{ row }">
      <div class="table-operate">
        <div v-for="(v, i) in buttons.inner" :key="`i-${i}`">
          <Divider v-if="i !== 0" type="vertical"/>
          <span>
            <Popconfirm
v-if="v.tip"
              placement="top"
              :title="v.tipContent"
              @confirm="handleCall(v, row)">
              <a>{{v.name}}</a>
            </Popconfirm>
            <a v-else @click="handleCall(v, row)">{{v.name}}</a>
          </span>
        </div>
      </div>
    </template>

    <template #expandRow="{row}">
      <slot name="expandRowContent" :row="row"></slot>
    </template>
  </vxe-grid>
</template>
<script lang="ts" name="XGrid">
import { Divider, Popconfirm } from 'ant-design-vue';
import { defineComponent, reactive, ref, toRaw, watch, watchPostEffect } from 'vue';
import { VxeGridPropTypes, VxeGridProps, VxeTablePropTypes, } from 'vxe-table';
import { pagerConfig } from './data';
// import { usePermission } from '/@/hooks/web/usePermission';
import { useRoute } from 'vue-router';
import { getCacheButtonList } from "/@/utils/my";



const props = {
  size: { type: String, default: 'medium' }, // null | 'medium' | 'small' | 'mini'
  isTree: { type: Boolean, default: false },
  isCheckbox: { type: Boolean, default: true },
  columns: { type: Array, default: () => [],},
  queryParams: {type: Object, default: {},},
  height: { type: [Number, String] as PropType<Number | String>, default: window.innerHeight - 103},
  border: {type: [String, Boolean], default: 'full'}, // default | full | outer | inner | none
  line: {type: Boolean, default: true},
  expandAll: {type: Boolean, default: true},
  stripe: {type: Boolean, default: true},
  showOverflow: {type: [String, Boolean], default: 'tooltip'}, // ellipsis | title | tooltip
  notCheckbox: {type: Array<Number | String>, default: () => null},
  checkStrictly: {type: Boolean, default: false,},
  optFixed: {type: [String, null] as PropType<String | null>, default: 'left',}, // left | right | null
  notButtons: {type: Array, default: []},
  printTop: { type: String, default: '' },
  printBottom: { type: String, default: '' },
  printStyle: { type: String, default: '' },
  footerMethod: Function,
  isSheet: {type: Boolean, default: false,},
  mergeFields: { type: Array<string>, default: [], },
  queryApiPostInterceptor: Function,
  queryApi: Function,
  queryAllApi: Function,
  deletesApi: Function,
}
const getValueOfKey = (row:any, key:string, fields:string[]) => {
  if (fields.includes(key)) {
    let arr = key?.split('.') || []
    // if (key === 'cate.name') {
    //   console.log(arr, arr.length, key, row[arr[0]])
    //   return row[key]
    // }
    if (arr.length > 1) {
      let one = row[arr[0]]
      if (one && typeof one === 'object') {
        return one[arr[1]]
      }
      return one || ''
    }
    return row[key]
  }
}
const EmitKeyOfCheckedCount = 'checked-count'
const allButtonList = getCacheButtonList()
const emits = [EmitKeyOfCheckedCount, ...(allButtonList?.map(e => e.func).filter(Boolean) || [])];
export default defineComponent({
  name: 'XGrid',
  components: { Divider, Popconfirm },
  inheritAttrs: true,
  props,
  emits,
  setup(props, { emit, expose }) {
    const insideQueryParams = ref();
    const xGrid = ref()
    const mergeRowMethod = ({ row, _rowIndex, column, visibleData }) => {
      const fields = props.mergeFields
      if (fields.length === 0) {
        return
      }
      // const cellValue = row[column.field]
      const cellValue = getValueOfKey(row, column.field, fields)
      if (cellValue && fields.includes(column.field)) {
        const prevRow = visibleData[_rowIndex - 1]
        let nextRow = visibleData[_rowIndex + 1]
        if (prevRow && getValueOfKey(prevRow, column.field, fields) === cellValue) {
          return { rowspan: 0, colspan: 0 }
        } else {
          let countRowspan = 1
          while (nextRow && getValueOfKey(nextRow, column.field, fields) === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex]
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 }
          }
        }
      }
    }
    const gridOptions = reactive<VxeGridProps>({
      border: props.border as VxeTablePropTypes.Border,
      resizable: true,
      round: true,
      showHeaderOverflow: true,
      showOverflow: props.showOverflow as VxeTablePropTypes.ShowOverflow,
      highlightHoverRow: true,
      keepSource: true,
      showFooter: !!(props.footerMethod),
      id: 'xgrid_'+new Date().getTime(),
      stripe: props.stripe,
      height: props.height as VxeTablePropTypes.Height,
      size: props.size as VxeTablePropTypes.Size,
      // columns: [...props.columns, 
      //         {title: '操作', sortable: false, visible: true, slots: {default: 'operate'}, 
      //         width: 80, align: 'center', fixed: props.optFixed,}] as VxeGridPropTypes.Columns,
      columns: (() => {
        return [
        ...props.columns.slice(0, 1),
        {title: '操作', sortable: false, visible: true, slots: {default: 'operate'}, width: 80, align: 'center', fixed: props.optFixed,},
        ...props.columns.slice(1),
        ] as VxeGridPropTypes.Columns
      })(),
      columnConfig: {
        useKey: true,
        isCurrent: true,
        isHover: true,
      },
      rowConfig: {
        useKey: true,
        isCurrent: true,
        isHover: false,
        keyField: 'ID',
      },
      // mouseConfig:{selected: false,},
      keyboardConfig: {isArrow: true, isEnter: true,},
      expandConfig: {
        expandAll: true,
        trigger: 'cell',
      },
      customConfig: {
        storage: true,
      },
      tooltipConfig: {
      },
      printConfig: {
        sheetName: '',
        mode: 'selected',
        // isMerge: true,
        style: props.printStyle,
        modes: ['current', 'selected', 'all'],
        columnFilterMethod: ({ column, }) => {
          return column.type !== 'checkbox';
        },
        beforePrintMethod: ({ content, options }) => {
          let result = props.printTop + content + props.printBottom;
          // result = `<div style="width:100%">` + result + `</div>`
          return result;
        }
      },
      sortConfig: {
        trigger: 'cell',
        remote: false
      },
      filterConfig: {
        remote: false
      },
      pagerConfig: pagerConfig,
      toolbarConfig: {
        slots: {
          buttons: 'toolbar_buttons',
          tools: 'tools_'
        },
      },
      importConfig: {
      },
      exportConfig: {
        remote: false,
        isMerge: true,
        types: ['xlsx'],
        modes: ['current', 'selected', 'all'],
        // columnFilterMethod({ column, $columnIndex }) {
        //   console.log(column)
        // },
      },
      checkboxConfig: {
        reserve: false,
        highlight: true,
        range: true,
        trigger: 'cell',
        checkStrictly: props.checkStrictly,
        checkMethod: ({row}) => {
          if (props.isSheet) {
            return !(row?.status === 4)
          }
          if (props.notCheckbox) {
            return !(props.notCheckbox.some((e:number) => e === row.id))
          }
          return true;
        },
      },
      spanMethod: mergeRowMethod,
      footerMethod: ({columns, data,}) => {
        if (props.footerMethod) {
          return props.footerMethod({columns, data,})
        }
        return [];
      },
      proxyConfig: {
        autoLoad: true,
        ajax: {
          // { page, sort, sorts, filters, form }
          query({ page, }) {
            // batchDeleteDisabled.value = true
            // let query = Object.assign({}, toRaw(props.queryParams), page)
            // let url_ = props.isTree ? `${url.value}/list` : `${url.value}/table`
            // return defHttp.get<any>({ url: url_, params: query });
            if (props.queryApi) {
              let params = Object.assign({}, toRaw(props.queryParams), page)
              if (props.queryApiPostInterceptor) {
                return props.queryApi(params).then(dd => {
                  return new Promise((resolve) => resolve(props.queryApiPostInterceptor!(dd)))
                })
              }
              return props.queryApi(params)
            }
          },
          queryAll() {
            if (props.queryAllApi) {
              let params = Object.assign({}, toRaw(props.queryParams),)
              return props.queryAllApi(params)
            }
          }
        }
      },
    });
 
    const checkboxCount = ref(' (0)')
    watchPostEffect(() => {
      if (xGrid.value) {
        checkboxCount.value = ` (${xGrid.value.getCheckboxRecords(true).length})`

        let innerLen = buttons.inner.length
        let opt = xGrid.value.getColumns().find((e:any) => e?.title === '操作')
        if (opt) {
          if (innerLen > 0 && props.columns.length > 0) {
            let width = 80
            if (innerLen > 1) {
              width = 70 * innerLen * 0.9;
            }
            opt.width = width
          } else {
            opt.visible = false
          }
        }
        xGrid.value.refreshColumn()
      }

      if (props.isTree && !gridOptions.treeConfig) { // 防止一直设置
        gridOptions.treeConfig = {
          rowField: 'id',
          // parentField: 'parentId',
          trigger: 'cell',
          lazy: false,
          accordion: false,
          showLine: props.line,
          expandAll: props.expandAll,
        }
        gridOptions!.checkboxConfig!.range = false;
        delete gridOptions.pagerConfig
      }
      if (!props.isCheckbox) {
        delete gridOptions.checkboxConfig
      }
    })

    watch(() => props.queryParams, (v1, _) => {
      insideQueryParams.value = v1
    }, {
      immediate: true,
      deep: true
    })

    const reload = (isReset?:boolean) => {
      batchDeleteDisabled.value = true
      oneDisabled.value = true
      gridOptions.loading = true

      let params = {}
      if (!isReset) {
        params = Object.assign({}, toRaw(insideQueryParams.value),)
      }
      if (props.queryApi) {
        props.queryApi(params).then(dd => {
          if (props.isTree) {
            xGrid.value.reloadData(dd)
          } else {
            xGrid.value.reloadData(dd?.result)
            let {pager} = xGrid.value.getProxyInfo()
            pager.total = dd?.page?.total
          }
        }).finally(() => {
          gridOptions.loading = false
          // insideQueryParams.value = {}
        })
      }
    }

    const handleDelete = (...params: number[]) => {
      if (params.length > 0) {
        if (props.deletesApi) {
          props.deletesApi(params).then(() => {
            batchDeleteDisabled.value = true
            reload()
          })
        }
      }
    }

    const batchDeleteDisabled = ref(true)
    const oneDisabled = ref(true)
    const checkedRowRef = ref() // 单行选中的数据
    function setCheckedRowRef (list:any[]) {
      if (list.length === 1) {
          checkedRowRef.value = toRaw(list[0])
          oneDisabled.value = false
      } else {
        checkedRowRef.value = null
        oneDisabled.value = true
      }
    }
    const checkboxChange = ({}) => {
      let checkedList = xGrid.value.getCheckboxRecords(true)
      setCheckedRowRef(checkedList)
      batchDeleteDisabled.value = !(checkedList.length > 0)
      emit('checked-count', checkedList.length)
    }
    const checkboxAll = ({ checked,}) => {
      setCheckedRowRef([])
      batchDeleteDisabled.value = !checked
      emit('checked-count', xGrid.value.getCheckboxRecords(true).length)
    }
    const checkboxRangeChange = ({}) => {
      let checkedList = xGrid.value.getCheckboxRecords(true)
      setCheckedRowRef(checkedList)
      batchDeleteDisabled.value = !(checkedList.length > 0)
      emit('checked-count', checkedList.length)
    }

    const handleCall = (btn:any, row?:any) => {
      if (btn.selectedCount > 0) {
        let checkedList = xGrid.value.getCheckboxRecords(true) || []
        handleDelete(...(checkedList.map((e:any) => e.ID)))
        emit(btn?.func, checkedList)
      } 
      else if(btn.ID === 9 && !!row) {
        handleDelete(row.ID)
      }
      else {
        emit(btn?.func as never, row)
      }
    }

    const route = useRoute();
    const buttonList = route.meta?.buttonList
    const buttons = reactive({
      topLeft: [] as any[],
      // topRight: [] as any [],
      inner: [] as any[],
    })
    if (buttonList) {
      if (props.notButtons.length > 0) { // 移除特定页面不显示的按钮
        // remove(buttonList, function(e) {
        //   return props.notButtons.some((nb:any) => nb.name === e.name)
        // })
      }

      buttons.topLeft = buttonList.filter(e => e.place === 0 && !props.notButtons.some((nb:any) => nb.name === e.name))
      buttons.inner = buttonList.filter(e => e.place === 2 && !props.notButtons.some((nb:any) => nb.name === e.name))

      let topRight = buttonList.filter(e => e.place === 1 && !props.notButtons.some((nb:any) => nb.name === e.name))
      topRight.forEach(e => {
        if (e.name === '刷新表') gridOptions!.toolbarConfig!.refresh = true;
        if (e.name === '导入') gridOptions!.toolbarConfig!.import = true;
        if (e.name === '导出') gridOptions!.toolbarConfig!.export = true;
        if (e.name === '打印') gridOptions!.toolbarConfig!.print = true;
        if (e.name === '最大化') gridOptions!.toolbarConfig!.zoom = true;
        if (e.name === '自定义列') gridOptions!.toolbarConfig!.custom = true;
      })
    }

    expose({
      reload,
      getGridRef() {
        return xGrid.value
      },
      setAllTreeExpand(expand:boolean) {
        xGrid.value.setAllTreeExpand(expand)
      },
      getCheckedList():any[] {
        return xGrid.value.getCheckboxRecords(true)
      },
      clearCheckboxRow() {
        xGrid.value.clearCheckboxRow()
      },
    })
    return {
      xGrid,
      gridOptions,
      buttons,
      checkboxCount,
      checkboxChange,
      checkboxAll,
      checkboxRangeChange,
      handleCall,
    }
  }
})

</script>
<style scoped>
.disabled {
  pointer-events: none;
  opacity: .5;
  -moz-opacity: .5;
  /* 黑白色 */
  -webkit-filter: grayscale(100%); /* Chrome, Safari, Opera */
  filter: grayscale(100%);
}
.btn{
  font-weight: bold;
}
/* span > a {
  font-size: .8rem;
} */

:deep().vxe-footer--row{
  background: rgba(250,250,250,.6);
  font-weight: bold;
}
.table-operate{
  display: flex;
  justify-content: center;
  align-items: center;
}
.table-operate a {
  display: inline-block;
  font-size: .97rem;
  background: linear-gradient(90deg, gray, rgba(200, 200, 200, 1));
  background-size: 0 3px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  /* // background-position: 100% 100%; */
  transition: .3s all;
  /* color: #0cc; */
}
.table-operate a:hover{
  transform: translateY(-2px);
  background-size: 100% 3px;
  padding-bottom: 0px;
}
</style>
